//运行程序，按遥控器按键，在数码管上显示相应的地址码-控制码（以16进制显示）
//	分两段，前段是地址码，后段为控制码，用点隔开，显示两字节，忽略反码
//	注意：使用12M晶振下调试
//头文件:
#include <reg52.h>

//IO引脚定义:
sbit SMG_q = P1^0;    //定义数码管阳级控制脚（千位）
sbit SMG_b = P1^1;	//定义数码管阳级控制脚（百位）
sbit SMG_s = P1^2;	//定义数码管阳级控制脚（十位）
sbit SMG_g = P1^3;	//定义数码管阳级控制脚（个位）

/********数据定义*************************************************************/
code unsigned char table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
							0x88,0x8c,0xc6,0xa1,0x86,0x8e};	//共阳数码管段值表 0-9 a-f
unsigned char l_posit=0;	//显示位置
unsigned char ly_disdate[4]={0,0,0,0};		//显示缓冲

unsigned char ly_lhj[4];					//保存NEC的四个字节数据，用户码前两个字节，控制码后两个字节
unsigned char ly_hwcc;	//红外接收计数
bit ly_hwf;				//红外引导码标志
bit ly_flag=0;			//成功接收标志

//函数声明:
void display();//定义显示函数，直接显示缓冲区数值


/***********主函数开始********************************************************/	
void main(void)
{
	EA=1;					//首先开启总中断
	EX1=1;  				//开启外部中断1,红外接收数据引脚
	IT1=1;        			//设置成下降沿触发方式
	TMOD=0X10;				//定时器1的方式1，16位计数器，用来计数时间
	while(1){	
		if(ly_flag){			//接收成功处理显示缓冲，以16进制显示
			ly_flag=0;
			ly_disdate[0]=ly_lhj[1]/16;
			ly_disdate[1]=ly_lhj[1]%16;
			ly_disdate[2]=ly_lhj[2]/16;
			ly_disdate[3]=ly_lhj[2]%16;
		}
		display();//显示缓冲内容	
	}		

}

/***********外中断1入口函数，P33引脚，红外线接收IC数据脚**************************/
void hongwai(void)   interrupt 2
{
	unsigned char lc;
	lc=TH1;				//这里只获取计数器高位来做判断足够精确了
	TL1=0;
	TH1=0;				//定时/计数器1初始值
	TR1=1;				//定时器以12M晶振12分频计数，即1us计数
	
	if(ly_hwf==1){	//表示引导码已确定，接收数据，否则先判断引导码
		if(lc>10){//超出2.25MS为非正常数值，退出，变量做复位，等待下次接收
			ly_hwf=0;
			ly_hwcc=0;
			TR1=0;
			return;
		}			
		
		ly_lhj[ly_hwcc/8]>>=1;			//数据由高位移入低位
		if(lc>6)					//时间量判断，数值编码1.125MS为0，2.25MS为1，计数器高位分别对应为4和8，因此我们用6来做中间值判断
				ly_lhj[ly_hwcc/8]|=0x80;
		ly_hwcc++;
		
    if(ly_hwcc==32){//32位接收完成，数值做复位处理，等待下次接收
			ly_flag=1;	//接收成功
			ly_hwf=0;
			ly_hwcc=0;
			TL1=0;
			TH1=0;
			TR1=0;
		}
  }
	else if((lc>50)&&(lc<54)){//判断引导码，NEC制引导码13.5MS（9+4.5），计数器高位值为52，给点误差值，我们用50和54来过滤
        ly_hwcc=0;
        ly_hwf=1;//是引导码，则下次中断进入数据接收处理
  }
	else{//不是引导码，也不是正确的数值，则停止计数器
		if(TH1)
			TR1=0;
	}
	TF1=0;
}

//显示函数，参数为显示内容
void display()
{
	P0=0XFF;			//	
	switch(l_posit){
	case 0:		//选择千位数码管，关闭其它位
		SMG_q=0;
		SMG_b=1;	
		SMG_s=1;		
		SMG_g=1;
		P0=table[ly_disdate[0]];	//输出显示内容
		break;
	case 1:		//选择百位数码管，关闭其它位
		SMG_q=1;
		SMG_b=0;	
		SMG_s=1;		
		SMG_g=1;
		P0=table[ly_disdate[1]]&0x7f;	//加上小数点
		break;
	case 2:		//选择十位数码管，关闭其它位
		SMG_q=1;
		SMG_b=1;	
		SMG_s=0;		
		SMG_g=1;
		P0=table[ly_disdate[2]];
		break;
	case 3:		//选择个位数码管，关闭其它位
		SMG_q=1;
		SMG_b=1;	
		SMG_s=1;		
		SMG_g=0;
		P0=table[ly_disdate[3]];
		break;
	}
	l_posit++;		//每调用一次将轮流显示一位
	if(l_posit>3)
		l_posit=0;	
}